package client

import (
	"fmt"
	"sync"
)

var (
	Clients = &ClientsMap{
		clients: map[string]*Client{},
	}
)

type ClientsMap struct {
	clients map[string]*Client
	sync.RWMutex
}

func (cm *ClientsMap) Range(fn func(uid string, c *Client) (over bool)) {
	cm.RLock()
	// 拷贝一份，防止长时间占用lock
	tmp := make([][2]interface{}, len(cm.clients))
	index := 0
	for k, v := range cm.clients {
		tmp[index] = [2]interface{}{k, v}
		index++
	}
	cm.RUnlock()
	for _, kv := range tmp {
		if kv[1] != nil {
			if over := fn(kv[0].(string), kv[1].(*Client)); over {
				break
			}
		}
	}
}

func (cm *ClientsMap) Get(uid string) *Client {
	cm.RLock()
	defer cm.RUnlock()
	return cm.clients[uid]
}

func (cm *ClientsMap) Remove(c *Client) error {
	if c == nil {
		return nil
	}
	info := c.GetRegisterInfo()
	uid := info.GetUID()
	cm.Lock()
	defer cm.Unlock()
	if catch := cm.clients[uid]; catch != nil {
		if catch.uuid != c.uuid {
			return fmt.Errorf("UID %v uuid is %v not %v", uid, catch.uuid, c.uuid)
		}
	} else {
		return fmt.Errorf("UID %v not exists", uid)
	}
	// 只有uid相等，且LastRegTime相等，才会移除
	delete(cm.clients, uid)
	return nil
}

func (cm *ClientsMap) Set(c *Client) {
	if c == nil {
		return
	}
	info := c.GetRegisterInfo()
	if uid := info.GetUID(); uid != "" {
		cm.Lock()
		defer cm.Unlock()
		cm.clients[uid] = c
	}
}
